package com.cskaoyan.controller.wx;

import com.cskaoyan.bean.User;
import com.cskaoyan.bean.basebean.BaseRespVo;
import com.cskaoyan.bean.basebean.DataBean;
import com.cskaoyan.bean.wx_search.MobileBo;
import com.cskaoyan.bean.wx_search.RegisterBo;
import com.cskaoyan.bean.wx_search.ResetBo;
import com.cskaoyan.exception.LoginFailException;
import com.cskaoyan.service.UserService;
import com.cskaoyan.shiro.MallToken;
import com.cskaoyan.utils.Md5Utils;
import com.google.gson.Gson;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
@RequestMapping("wx/auth")
public class WxAuthController {

    @Autowired
    UserService userService;

    @Autowired
    private JavaMailSender javaMailSender;

    private Map<String, Object> resultMap = new HashMap<>();

    @RequestMapping("login")
    public BaseRespVo login(@RequestBody Map map, HttpServletRequest request) throws LoginFailException {
        Subject subject = SecurityUtils.getSubject();

        String username = (String) map.get("username");
        String password = (String) map.get("password");
        //TODO：认证
        try {
            password = Md5Utils.getMd5(password, "password");
            MallToken wxToken = new MallToken(username, password, "wx");
            subject.login(wxToken);
            //subject.login → 认证 → Authenticator执行认证 → realm的doGetAuthenInfo
            //可以获得认证状态
            //boolean authenticated = subject.isAuthenticated();
//        获得用户信息 → realm里的doGetAuthenInfo中的构造的Principal信息
            //Object primaryPrincipal = subject.getPrincipals().getPrimaryPrincipal();
        } catch (Exception e) {
            //e.printStackTrace();
            throw new LoginFailException();
        }
        //User user1 = userService.selectUserByUsername(username);
        //登录成功
        DataBean dataBean = new DataBean();
        DataBean.AdminInfoBean adminInfoBean = new DataBean.AdminInfoBean();
        User user = userService.selectUserByUsername(username);
        adminInfoBean.setAvatar(user.getAvatar());
        adminInfoBean.setNickName(user.getNickname());
        dataBean.setAdminInfo(adminInfoBean);
        String sessionId = (String) subject.getSession().getId();
        dataBean.setToken(sessionId);
        String ip = request.getRemoteAddr();
        //如果是本地访问则将ip修改为127.0.0.1
        ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
        userService.updateUserLoginInfo(user.getId(), ip, sessionId);
        return BaseRespVo.ok(dataBean);
    }

    @RequestMapping("logout")
    public BaseRespVo logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        return BaseRespVo.ok();
    }

    @RequestMapping("regCaptcha")
    public BaseRespVo regCaptcha(@RequestBody MobileBo mobileBo) {
        SimpleMailMessage message = new SimpleMailMessage();
        String code = VerifyCode(6);
        String sender = "663709962@qq.com";
        message.setFrom(sender);
        message.setTo(mobileBo.getMobile());
        message.setSubject("商城系统");
        message.setText("【商城系统】你的验证码为：" + code + "，有效时间为5分钟(若不是本人操作，可忽略该条邮件)");
        try {
            javaMailSender.send(message);
            saveCode(code);
            return BaseRespVo.ok();
        } catch (Exception e) {
            e.printStackTrace();
            return BaseRespVo.fail("邮件发送失败");
        }

    }

    private String VerifyCode(int n) {
        Random r = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < n; i++) {
            int ran1 = r.nextInt(10);
            sb.append(String.valueOf(ran1));
        }
//        System.out.println(sb);
        return sb.toString();
    }

    //保存验证码和时间
    private void saveCode(String code) {
        SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MINUTE, 5);
        String currentTime = sf.format(c.getTime());// 生成5分钟后时间，用户校验是否过期
        resultMap.put("code", code);
        resultMap.put("tamp", currentTime);
    }

    @RequestMapping("register")
    public BaseRespVo register(@RequestBody RegisterBo registerBo) throws Exception {
        if (resultMap != null) {
            String needCode = (String) resultMap.get("code");
            String tamp = resultMap.get("tamp").toString();
            SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");//当前时间
            Calendar c = Calendar.getInstance();
            String currentTime = sf.format(c.getTime());
            if (tamp.compareTo(currentTime) > 0) {
                String code = registerBo.getCode();
                if (needCode.equalsIgnoreCase(code)) {
                    //校验成功 注册用户
                    userService.insertUser(registerBo);
                    return BaseRespVo.ok();
                } else {
                    //验证码不正确，校验失败
                    return BaseRespVo.fail("验证码错误");
                }
            } else {
                // 超时
                return BaseRespVo.fail("验证码超时");
            }
        }
        return BaseRespVo.fail("注册失败");
    }

    @RequestMapping("reset")
    public BaseRespVo reset(@RequestBody ResetBo ResetBo) throws Exception {
        if (resultMap != null) {
            String needCode = (String) resultMap.get("code");
            String tamp = resultMap.get("tamp").toString();
            SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHHmmss");//当前时间
            Calendar c = Calendar.getInstance();
            String currentTime = sf.format(c.getTime());
            if (tamp.compareTo(currentTime) > 0) {
                String code = ResetBo.getCode();
                if (needCode.equalsIgnoreCase(code)) {
                    //校验成功 注册用户
                    boolean result = userService.resetUserPwd(ResetBo);
                    return result ? BaseRespVo.ok() : BaseRespVo.fail("修改密码失败");
                } else {
                    //验证码不正确，校验失败
                    return BaseRespVo.fail("验证码错误");
                }
            } else {
                // 超时
                return BaseRespVo.fail("验证码超时");
            }
        }
        return BaseRespVo.fail("注册失败");
    }
}
